#!/bin/bash
#================================================================================================
#
# This file is licensed under the terms of the GNU General Public
# License version 2. This program is licensed "as is" without any
# warranty of any kind, whether express or implied.
#
# This file is a part of the Rebuild Armbian
# https://github.com/ophub/amlogic-s9xxx-armbian
#
# Function: Install armbian to eMMC
# Copyright (C) 2021- https://github.com/unifreq/openwrt_packit
# Copyright (C) 2022- https://github.com/7Ji/ampart
# Copyright (C) 2021- https://github.com/ophub/amlogic-s9xxx-armbian
#
# Command: armbian-install
# Optional parameter meaning: -m = ues Mainline_u-boot
#                             -a = ues Ampart
#                             -l = List show all
#
# Command optional parameters:  armbian-install -m yes/no -a yes/no -l yes/no
# Use mainline u-boot command:  armbian-install -m yes
# Disable ampart tool command:  armbian-install -a no
# list show all command:        armbian-install -l yes
#
#======================================== Functions list ========================================
#
# error_msg          : Output error message
# check_depends      : Check dependencies
# init_var           : Initialize all variables
# show_aml_model     : Display the model list
# set_rootfs_type    : Set the type of file system
# ampart_tool        : Repartition using ampart
# create_partition   : Create emmc partition
# copy_bootfs        : Copy bootfs partition files
# copy_rootfs        : Copy rootfs partition files
#
#==================================== Set default parameters ====================================
#
# Use mainline u-boot by default (-m)
auto_mainline_uboot="no"
# Use ampart partition tool by default (-a)
use_ampart="yes"
# Show all device list by default (-l)
show_all_list="no"

# Set install list profile
model_conf="/data/model_database.conf"
# Add custom armbian firmware information
ophub_release_file="/etc/ophub-release"
# Set banner's ${BOARD_NAME}: such as [ s905x3 ]
armbian_release_file="/etc/armbian-release"
# Set the installation file preprocessing directory
tmp_path="/ddbr"

# Set font color
STEPS="[\033[95m STEPS \033[0m]"
INFO="[\033[94m INFO \033[0m]"
SUCCESS="[\033[92m SUCCESS \033[0m]"
OPTIONS="[\033[93m OPTIONS \033[0m]"
ERROR="[\033[91m ERROR \033[0m]"
#
#================================================================================================

# Encountered a serious error, abort the script execution
error_msg() {
    echo -e "${ERROR} ${1}"
    exit 1
}

# Check dependencies
check_depends() {
    echo -e "${STEPS} Start checking dependencies..."

    is_missing="0"
    necessary_packages=("tar" "hexdump" "mkfs.vfat" "mkfs.ext4" "mkfs.btrfs" "parted" "losetup" "fdisk" "lsblk")
    install_packages=("tar" "bsdextrautils" "dosfstools" "e2fsprogs" "btrfs-progs" "parted" "mount" "fdisk" "util-linux")

    i="1"
    for package in ${necessary_packages[*]}; do
        [[ -n "$(which "${package}" 2>/dev/null)" ]] || is_missing="1"
        let i++
    done

    if [[ "${is_missing}" -eq "1" ]]; then
        echo -e "${INFO} Start installing the necessary dependencies."
        sudo apt-get update
        sudo apt-get install -y ${install_packages[*]}
        [[ "${?}" -eq "0" ]] || error_msg "Dependency installation failed, stop install."
    else
        echo -e "${INFO} Dependency check completes, Start installing Armbian."
    fi
}

# Initialize all variables
init_var() {
    echo -e "${STEPS} Start initializing the environment..."

    # If it is followed by [ : ], it means that the option requires a parameter value
    get_all_ver="$(getopt "m:a:l:" "${@}")"

    while [[ -n "${1}" ]]; do
        case "${1}" in
        -m | --Mainline_u-boot)
            if [[ -n "${2}" ]]; then
                [[ "${2}" == "yes" ]] && auto_mainline_uboot="yes" || auto_mainline_uboot="no"
                shift
            else
                error_msg "Invalid -m parameter [ ${2} ]!"
            fi
            ;;
        -a | --Ampart_tool)
            if [[ -n "${2}" ]]; then
                [[ "${2}" == "yes" ]] && use_ampart="yes" || use_ampart="no"
                shift
            else
                error_msg "Invalid -a parameter [ ${2} ]!"
            fi
            ;;
        -l | --List_all)
            if [[ -n "${2}" ]]; then
                [[ "${2}" == "yes" ]] && show_all_list="yes" || show_all_list="no"
                shift
            else
                error_msg "Invalid -s parameter [ ${2} ]!"
            fi
            ;;
        *)
            error_msg "Invalid option [ ${1} ]!"
            ;;
        esac
        shift
    done

    # Display settings results
    echo -e "${INFO} Use mainline u-boot: [ ${auto_mainline_uboot} ]"
    echo -e "${INFO} Using the Ampart tool: [ ${use_ampart} ]"
    echo -e "${INFO} Show all lists: [ ${show_all_list} ]"

    # Find a list of devices of the same family
    SEARCH_FAMILY=""
    [[ "${show_all_list}" == "no" ]] && {
        [[ -s "${ophub_release_file}" ]] || error_msg "[ ${ophub_release_file} ] file is missing!"
        source "${ophub_release_file}" && SEARCH_FAMILY="$(basename ${FAMILY})"
        [[ -n "${SEARCH_FAMILY}" ]] && SEARCH_FAMILY=":${SEARCH_FAMILY}:"
    }

    # Check if the ${model_conf} file exists
    [[ -s "${model_conf}" ]] || error_msg "[ ${model_conf} ] file is missing!"
    model_database="$(cat ${model_conf} | sed -e 's/NA//g' -e 's/NULL//g' -e 's/[ ][ ]*//g' | grep -E "^[0-9]{1,3}:.*${SEARCH_FAMILY}.*")"
    [[ -n "${model_database}" ]] || error_msg "The [ ${SEARCH_FAMILY} ] series in the [ ${model_conf} ] file is empty and does not support writing to eMMC."

    # Check the current system running disk
    root_devname="$(df / | tail -n1 | awk '{print $1}' | awk -F '/' '{print substr($3, 1, length($3)-2)}')"
    if lsblk -l | grep -E "^${root_devname}boot0" >/dev/null; then
        error_msg "You are running in eMMC mode, please boot system with usb or tf card!"
    fi

    # Find emmc disk, first find emmc containing boot0 partition
    install_emmc="$(lsblk -l -o NAME | grep -oE '(mmcblk[0-9]?boot0)' | sed "s/boot0//g")"
    # Find emmc disk, find emmc that does not contain the boot0 partition
    [[ -z "${install_emmc}" ]] && install_emmc="$(lsblk -l -o NAME | grep -oE '(mmcblk[0-9]?)' | grep -vE ^${root_devname} | sort | uniq)"
    # Check if emmc exists
    [[ -z "${install_emmc}" ]] && error_msg "The eMMC storage not found in this device!"
    # Location of emmc
    DEV_EMMC="/dev/${install_emmc}"
    echo -e "${INFO} The device eMMC name: [ ${DEV_EMMC} ]"

    # Create a file preprocessing directory
    [[ -d "${tmp_path}" ]] && rm -rf ${tmp_path}/*
    DIR_INSTALL="${tmp_path}/install"
    mkdir -p ${DIR_INSTALL} && chmod 777 ${tmp_path}

    # Regenerate new machine-id
    rm -f /etc/machine-id /var/lib/dbus/machine-id
    dbus-uuidgen --ensure=/etc/machine-id
    dbus-uuidgen --ensure

    # Generate New ROOTFS UUID
    ROOTFS_UUID="$(cat /proc/sys/kernel/random/uuid)"
    [[ -z "${ROOTFS_UUID}" ]] && ROOTFS_UUID="$(uuidgen)"
    [[ -z "${ROOTFS_UUID}" ]] && error_msg "The new UUID is invalid, cannot continue."

    # Get kernel TEXT_OFFSET, For u-boot.ext and u-boot.emmc
    # With TEXT_OFFSET patch is [ 0108 ], without TEXT_OFFSET patch is [ 0000 ]
    K510="1"
    [[ "$(hexdump -n 15 -x "/boot/zImage" 2>/dev/null | head -n 1 | awk '{print $7}')" == "0108" ]] && K510="0"

    # Get random macaddr
    mac_hexchars="0123456789ABCDEF"
    mac_end="$(for i in {1..6}; do echo -n ${mac_hexchars:$((${RANDOM} % 16)):1}; done | sed -e 's/\(..\)/:\1/g')"
    random_macaddr="9E:61${mac_end}"
}

# Search the model list
search_aml_model() {
    local search_soc_id="${1}"
    local ret_count="$(echo "${model_database}" | grep -E "^${search_soc_id}:" | wc -l)"
    if [[ "${ret_count}" -eq "1" ]]; then
        echo "${model_database}" | grep -E "^${search_soc_id}:"
    fi
}

# Functions: Displays a list of supported amlogic devices
# Configure: View ${model_database}
# Explain:   1.ID  2.MODEL  3.SOC  4.FDTFILE  5.UBOOT_OVERLOAD  6.MAINLINE_UBOOT  7.BOOTLOADER_IMG  8.KERNEL_BRANCH  9.PLATFORM  10.FAMILY  11.BOARD  12.BUILD
# Example:   402:GT-King-Pro:s922x:meson-g12b-gtking-pro.dtb:u-boot-gtkingpro.bin:gtkingpro-u-boot.bin.sd.bin:NA:all:amlogic:meson-g12b:s922x:yes
show_aml_model() {
    echo -e "${STEPS} Start selecting device..."

    printf "%-s\n" "--------------------------------------------------------------------------------------"
    printf "%-5s %-10s %-30s %-50s\n" ID SOC MODEL DTB
    printf "%-s\n" "--------------------------------------------------------------------------------------"
    printf "%-5s %-10s %-30s %-50s\n" $(echo "${model_database}" | grep -E "^[0-9]{1,3}:.*" | awk -F':' '{print $1,$3,$2,$4}')
    printf "%-5s %-10s %-30s %-50s\n" 0 Other Customize Enter-custom-dtb-name
    printf "%-s\n" "--------------------------------------------------------------------------------------"

    echo -ne "${OPTIONS} Please Input ID: "
    read boxid
    if [[ "${boxid}" -eq "0" ]]; then
        read -p "Please Input SoC Name(such as s9xxx): " AMLOGIC_SOC
        AMLOGIC_SOC="${AMLOGIC_SOC}"
        #
        read -p "Please Input DTB Name(such as meson-xxx.dtb): " FDTFILE
        FDTFILE="${FDTFILE}"
        #
        read -p "Please Input UBOOT_OVERLOAD Name(such as u-boot-xxx.bin): " UBOOT_OVERLOAD
        UBOOT_OVERLOAD="${UBOOT_OVERLOAD}"
        #
        read -p "Please Input MAINLINE_UBOOT Name(such as xxx-u-boot.bin.sd.bin): " MAINLINE_UBOOT
        MAINLINE_UBOOT="${MAINLINE_UBOOT}"
        #
        read -p "Please Input BOOTLOADER_IMG Name(such as xxx-bootloader.img): " BOOTLOADER_IMG
        BOOTLOADER_IMG="${BOOTLOADER_IMG}"
    else
        ret="$(search_aml_model "${boxid}")"
        [[ -z "${ret}" ]] && error_msg "Input error, exit!"

        AMLOGIC_SOC="$(echo "${ret}" | awk -F ':' '{print $3}')"
        FDTFILE="$(echo "${ret}" | awk -F ':' '{print $4}')"
        UBOOT_OVERLOAD="$(echo "${ret}" | awk -F ':' '{print $5}')"
        MAINLINE_UBOOT="$(echo "${ret}" | awk -F ':' '{print $6}')"
        BOOTLOADER_IMG="$(echo "${ret}" | awk -F ':' '{print $7}')"
    fi

    echo -e "${INFO} Input Box ID: [ ${boxid} ]"
    echo -e "${INFO} FDTFILE: [ ${FDTFILE} ]"
    echo -e "${INFO} MAINLINE_UBOOT: [ ${MAINLINE_UBOOT} ]"
    echo -e "${INFO} BOOTLOADER_IMG:  [ ${BOOTLOADER_IMG} ]"
    echo -e "${INFO} UBOOT_OVERLOAD: [ ${UBOOT_OVERLOAD} ]"
    echo -e "${INFO} K510: [ ${K510} ]"

    # Check dtb file
    [[ -n "${FDTFILE}" && -f "/boot/dtb/amlogic/${FDTFILE}" ]] || error_msg "The [ ${FDTFILE} ] is missing, stop install."
    # Check UBOOT_OVERLOAD file
    [[ -n "${UBOOT_OVERLOAD}" && -f "/boot/${UBOOT_OVERLOAD}" ]] || error_msg "The [ ${UBOOT_OVERLOAD} ] is missing, stop install."
}

# Set the type of file system
set_rootfs_type() {
    echo -e "${STEPS} Start selecting file system type..."
    cat <<EOF
-----------------------------------------------
ID  TYPE
-----------------------------------------------
1   ext4
2   btrfs
-----------------------------------------------
EOF
    echo -ne "${OPTIONS} Please Input ID: "
    read filetype
    if [[ "${filetype}" -eq "2" || "${filetype}" == "btrfs" ]]; then
        file_system_type="btrfs"
        uenv_mount_string="UUID=${ROOTFS_UUID} rootflags=compress=zstd:6 rootfstype=btrfs"
        fstab_mount_string="discard,defaults,noatime,compress=zstd:6"
    else
        file_system_type="ext4"
        uenv_mount_string="UUID=${ROOTFS_UUID} rootflags=data=writeback rw rootfstype=ext4"
        fstab_mount_string="discard,defaults,noatime,errors=remount-ro"
    fi
    echo -e "${INFO} Input Type ID: [ ${filetype} ]"
    echo -e "${INFO} The type of file system: [ ${file_system_type} ]"
}

# Project repository:   https://github.com/7Ji/ampart
# Download from:        https://github.com/7Ji/ampart/releases/download/v1.2/ampart-v1.2-aarch64-static.gz
# Function description: ampart is a partitioning tool. Can repartition eMMC inside Amlogic device.
ampart_tool() {
    # declare the partition layout
    local snapshot_expected='data::-1:4'

    # Note there's no quote around ${snapshot_expected}
    ampart "${DEV_EMMC}" --mode dclone ${snapshot_expected} &>/dev/null
    if ((${?})); then
        # Handle the situation where ampart fails to change the layout
        return 1
    fi

    local log="$(ampart "${DEV_EMMC}" --mode dsnapshot 2>/dev/null)"
    if ((${?})); then
        # Handle the situation where ampart fails to read the new partitions
        return 2
    fi

    local snapshots
    readarray -d $'\n' -t snapshots <<<"${log}"

    # compare snapshots, 0 here refers to the decimal one
    if [[ "${snapshots[0]}" == "${snapshot_expected}" ]]; then
        # Successfully written the partitions
        return 0
    else
        # Result partitions different, maybe should handle it
        return 3
    fi
}

# Create emmc partition
create_partition() {
    cd /
    echo -e "${STEPS} Start creating eMMC partition..."

    # Disable the system's partition adjustment service
    systemctl stop armbian-resize-filesystem.service
    systemctl disable armbian-resize-filesystem.service

    # Backup the bootloader, if necessary for system recovery
    [[ -d "/usr/lib/u-boot" ]] || mkdir -p /usr/lib/u-boot
    MYBOX_UBOOT="/usr/lib/u-boot/mybox-bootloader.img"
    [[ -f "${MYBOX_UBOOT}" ]] && rm -f ${MYBOX_UBOOT}
    echo -e "${INFO} Start backing up the default bootloader."
    dd if="${DEV_EMMC}" of="${MYBOX_UBOOT}" bs=1M count=4 conv=fsync
    [[ "${?}" -eq "0" ]] || error_msg "Using dd to backup [ ${MYBOX_UBOOT} ] failed."

    # Clear emmc disk data
    exists_pts="$(parted ${DEV_EMMC} print 2>/dev/null | grep 'primary' | wc -l)"
    if [[ "${exists_pts}" -gt "0" ]]; then
        i=1
        while [[ "${i}" -le "${exists_pts}" ]]; do
            parted -s ${DEV_EMMC} rm ${i} 2>/dev/null
            let i++
        done
    fi
    #dd if=/dev/zero of=${DEV_EMMC} bs=512 count=1 conv=fsync

    # Use the ampart partition tool
    AMPART_STATUS="no"
    [[ -x "/usr/bin/ampart" && "${use_ampart}" == "yes" ]] && {
        ampart_tool
        [[ "${?}" -eq "0" ]] && AMPART_STATUS="yes" && echo -e "${STEPS} Use ampart partition successfully."
    }

    # Set partition size (Unit: MiB)
    if [[ "${AMPART_STATUS}" == "yes" ]]; then
        BLANK1="117" # After using the ampart partition, it can be used after [ 117 MiB ]
        BOOT="256"
        BLANK2="0"
    elif [[ "${AMLOGIC_SOC}" == "s912" || "${AMLOGIC_SOC}" == "s905d" ]]; then
        BLANK1="68"
        BOOT="512"
        BLANK2="220"
    elif [[ "${AMLOGIC_SOC}" == "s905x" ]]; then
        BLANK1="700"
        BOOT="160"
        BLANK2="0"
    elif [[ "${AMLOGIC_SOC}" == "s905l3a" && "${boxid}" -eq "304" ]]; then
        BLANK1="570" # e900v22c/d: The first [ 570 MiB ] is not writable.
        BOOT="256"
        BLANK2="0"
    elif [[ "${AMLOGIC_SOC}" == "s905l3a" && "${boxid}" -eq "305" ]]; then
        BLANK1="108" # CM311-1a-YST: Must skip [ 108 MiB ]
        BOOT="512"   # A total of [ 1024 MiB ] can be used in this block, gave up [ 1024-512=512 MiB ]
        BLANK2="778" # Can set the rootfs partition after [ 1398 MiB ] of the total disk, Multi-backward offset 100 MiB, [ 1398-108-512=778 MiB ]
    elif [[ "${AMLOGIC_SOC}" == "s905l3b" ]]; then
        BLANK1="128" # https://github.com/janko888/MBH-M30xA
        BOOT="513"   # M302A/M304A, Compatible with Android 4 and Android 9 firmware
        BLANK2="720"
    elif [[ "${FDTFILE}" == "meson-sm1-skyworth-lb2004-a4091.dtb" ]]; then
        BLANK1="108" # Tencent Aurora 3Pro: Must skip [ 108 MiB ]
        BOOT="512"   # A total of [ 768 MiB ] can be used in this block, gave up [ 768-512=256 MiB ]
        BLANK2="562" # Can set the rootfs partition after [ 1182 MiB ] of the total disk, [ 1182-108-512=562 MiB ]
    else
        BLANK1="68"
        BOOT="256"    # S905x3: A total of [ 1120 MiB ] can be used in this block, and the remaining [ 864 MiB ] can be used.
        BLANK2="1026" # Can set the rootfs partition after [ 1350 MiB ] of the total disk.
    fi

    # Format emmc disk
    echo -e "${INFO} Start create MBR and partittion."
    parted -s "${DEV_EMMC}" mklabel msdos
    parted -s "${DEV_EMMC}" mkpart primary fat32 $((BLANK1))MiB $((BLANK1 + BOOT - 1))MiB
    parted -s "${DEV_EMMC}" mkpart primary ${file_system_type} $((BLANK1 + BOOT + BLANK2))MiB 100%
    [[ "${?}" -eq "0" ]] || error_msg "Failed to create partition using [ parted ]."

    # Write bootloader
    if [[ -n "${MAINLINE_UBOOT}" && -f "/usr/lib/u-boot/${MAINLINE_UBOOT}" && "${auto_mainline_uboot}" == "yes" ]]; then
        echo -e "${INFO} Write Mainline bootloader: [ ${MAINLINE_UBOOT} ]"
        dd if="/usr/lib/u-boot/${MAINLINE_UBOOT}" of="${DEV_EMMC}" conv=fsync bs=1 count=444
        dd if="/usr/lib/u-boot/${MAINLINE_UBOOT}" of="${DEV_EMMC}" conv=fsync bs=512 skip=1 seek=1
    elif [[ -n "${BOOTLOADER_IMG}" && -f "/usr/lib/u-boot/${BOOTLOADER_IMG}" ]]; then
        echo -e "${INFO} Write Android bootloader: [ ${BOOTLOADER_IMG} ]"
        dd if="/usr/lib/u-boot/${BOOTLOADER_IMG}" of="${DEV_EMMC}" conv=fsync bs=1 count=444
        dd if="/usr/lib/u-boot/${BOOTLOADER_IMG}" of="${DEV_EMMC}" conv=fsync bs=512 skip=1 seek=1
    elif [[ -n "${MYBOX_UBOOT}" && -f "${MYBOX_UBOOT}" ]]; then
        echo -e "${INFO} Write the mybox bootloader: [ ${MYBOX_UBOOT} ]"
        dd if="${MYBOX_UBOOT}" of="${DEV_EMMC}" conv=fsync bs=1 count=444
        dd if="${MYBOX_UBOOT}" of="${DEV_EMMC}" conv=fsync bs=512 skip=1 seek=1
    fi
    [[ "${?}" -eq "0" ]] || error_msg "Failed to write bootloader using [ dd ]."
}

# Copy bootfs partition files
copy_bootfs() {
    cd /
    echo -e "${STEPS} Start processing the BOOTFS partition..."

    PART_BOOT="${DEV_EMMC}p1"

    if grep -q ${PART_BOOT} /proc/mounts; then
        echo -e "${INFO} Unmounting BOOT partiton."
        umount -f ${PART_BOOT}
        [[ "${?}" -eq "0" ]] || error_msg "Failed to umount [ ${PART_BOOT} ]."
    fi

    echo -e "${INFO} Start formatting BOOTFS partition..."
    mkfs.vfat -F 32 -n "BOOT_EMMC" ${PART_BOOT}
    [[ "${?}" -eq "0" ]] || error_msg "Failed to format using [ mkfs.vfat ]."

    mount -o rw ${PART_BOOT} ${DIR_INSTALL}
    [[ "${?}" -ne "0" ]] && error_msg "Failed to mount BOOTFS partition."

    echo -e "${INFO} Start copy BOOTFS partition data."
    cp -rf /boot/* ${DIR_INSTALL}
    rm -rf ${DIR_INSTALL}/'System Volume Information'

    echo -e "${INFO} Generate the new [ uEnv.txt ] file."
    rm -f ${DIR_INSTALL}/uEnv.txt
    cat >${DIR_INSTALL}/uEnv.txt <<EOF
LINUX=/vmlinuz-linux-aarch64-flippy
INITRD=/initramfs-linux-aarch64-flippy-fallback.uimg
FDT=/dtbs/linux-aarch64-flippy/amlogic/${FDTFILE}
APPEND=root=UUID=${uuid_root} rw audit=0 apt_blkdevs=mmcblk2
EOF

    # If the [ /boot/extlinux ] file exists, create a new one.
    if [[ -f "${DIR_INSTALL}/extlinux" ]]; then
        echo -e "${INFO} Generate the new [ extlinux.conf ] file."
        BOOT_CONF="extlinux.conf"
        rm -rf ${DIR_INSTALL}/extlinux
        mkdir -p ${DIR_INSTALL}/extlinux
        cat >${DIR_INSTALL}/extlinux/extlinux.conf <<EOF
LABEL   Arch Linux ARM
LINUX   /vmlinuz-linux-aarch64-flippy
INITRD  /initramfs-linux-aarch64-flippy-fallback.uimg
FDT     /dtbs/linux-aarch64-flippy/amlogic/${FDTFILE}
APPEND  root=UUID=${uuid_root} rw audit=0 apt_blkdevs=mmcblk2
EOF
    else
        BOOT_CONF="uEnv.txt"
        rm -rf ${DIR_INSTALL}/extlinux
    fi

    rm ${DIR_INSTALL}/s9*
    rm ${DIR_INSTALL}/aml*
    mv -f ${DIR_INSTALL}/boot-emmc.ini ${DIR_INSTALL}/boot.ini
    sed -i "s|u-boot.ext|u-boot.emmc|g" ${DIR_INSTALL}/boot.ini
    mv -f ${DIR_INSTALL}/boot-emmc.scr ${DIR_INSTALL}/boot.scr
    mv -f ${DIR_INSTALL}/boot-emmc.cmd ${DIR_INSTALL}/boot.cmd
    cp /data/boot.scr ${DIR_INSTALL}/boot.scr
    # Copy u-boot.ext and u-boot.emmc
    if [[ "${K510}" -eq "1" || "${auto_mainline_uboot}" == "yes" ]] && [[ -n "${UBOOT_OVERLOAD}" && -f "${DIR_INSTALL}/${UBOOT_OVERLOAD}" ]]; then
        echo -e "${INFO} Copy [ ${UBOOT_OVERLOAD} ] to u-boot.emmc"
        if [[ -f "${DIR_INSTALL}/u-boot.ext" ]]; then
            cp -f ${DIR_INSTALL}/u-boot.ext ${DIR_INSTALL}/u-boot.emmc
        else
            cp -f ${DIR_INSTALL}/${UBOOT_OVERLOAD} ${DIR_INSTALL}/u-boot.ext
            cp -f ${DIR_INSTALL}/${UBOOT_OVERLOAD} ${DIR_INSTALL}/u-boot.emmc
        fi
        chmod +x ${DIR_INSTALL}/u-boot.ext
        chmod +x ${DIR_INSTALL}/u-boot.emmc
    fi

    sync && sleep 3
    umount -f ${DIR_INSTALL}
    [[ "${?}" -eq "0" ]] || error_msg "Failed to umount [ ${DIR_INSTALL} ]."
}

# Copy rootfs partition files
copy_rootfs() {
    cd /
    echo -e "${STEPS} Start processing the rootfs partition..."
    PART_BOOT="${DEV_EMMC}p1"
    PART_ROOT="${DEV_EMMC}p2"
    if grep -q ${PART_ROOT} /proc/mounts; then
        echo -e "${INFO} Unmounting ROOT partiton."
        umount -f ${PART_ROOT}
        [[ "${?}" -eq "0" ]] || error_msg "Failed to umount [ ${PART_ROOT} ]."
    fi

    echo -e "${INFO} Start formatting ROOTFS partition..."
    if [[ "${file_system_type}" == "btrfs" ]]; then
        mkfs.btrfs -f -U ${ROOTFS_UUID} -L "ROOTFS_EMMC" -m single ${PART_ROOT}
        [[ "${?}" -eq "0" ]] || error_msg "Failed to format using [ mkfs.btrfs ]"

        mount -t btrfs -o compress=zstd:6 ${PART_ROOT} ${DIR_INSTALL}
        [[ "${?}" -ne "0" ]] && error_msg "Failed to mount ROOTFS partition."
    else
        mkfs.ext4 -F -q -U ${ROOTFS_UUID} -L "ROOTFS_EMMC" -b 4k -m 0 ${PART_ROOT}
        [[ "${?}" -eq "0" ]] || error_msg "Failed to format using [ mkfs.ext4 ]"

        mount -t ext4 ${PART_ROOT} ${DIR_INSTALL}
        [[ "${?}" -ne "0" ]] && error_msg "Failed to mount ROOTFS partition."
    fi

    echo -e "${INFO} Start copy ROOTFS partition data."
    #tar xvpfz /data/centos7.9-pure-add-wifi-bluetooth.tgz -C  ${DIR_INSTALL}/
    #bsdtar -C ${DIR_INSTALL} --acls --xattrs -xvpzf /data/ArchLinuxARM-aarch64-Amlogic-20230216_011012-root.tar.xz
    cd  ${DIR_INSTALL}/
    #pv  /data/ArchLinuxARM-aarch64-Amlogic-20230216_011012-root.tar.xz | tar -xpJf -
    pv /data/ArchLinuxARM-aarch64-Amlogic-20230225_150037-root.tar.xz | tar -xpJf -
    cd 
# Create relevant directories
    mkdir -p ${DIR_INSTALL}/{boot/,dev/,media/,mnt/,proc/,run/,sys/,tmp/}
    chmod 777 ${DIR_INSTALL}/tmp
    # Copy the relevant directory
    #COPY_SRC="etc home lib64 opt root selinux srv usr var"
    #for src in ${COPY_SRC}; do
     #   echo -e "${INFO} Copy the [ ${src} ] directory."
    #    tar -cf - ${src} | (
   #         cd ${DIR_INSTALL}
  #          tar -xf -
 #       )
#    done
    # Create relevant symbolic link
#    ln -sf /usr/bin ${DIR_INSTALL}/bin
#    ln -sf /usr/lib ${DIR_INSTALL}/lib
#    ln -sf /usr/sbin ${DIR_INSTALL}/sbin

    echo -e "${INFO} Generate the new fstab file."
    rm -f ${DIR_INSTALL}/etc/fstab
    cat >${DIR_INSTALL}/etc/fstab <<EOF
UUID=${ROOTFS_UUID}    /        ${file_system_type}    ${fstab_mount_string}      0 1
LABEL=BOOT_EMMC        /boot    vfat                   discard,defaults           0 2
tmpfs                  /tmp     tmpfs                  defaults,nosuid            0 0
EOF

    echo -e "Copy boot files needed in archlinux."
    mount -o rw ${PART_BOOT} ${DIR_INSTALL}/mnt
    cp  ${DIR_INSTALL}/boot/initramfs-linux-aarch64-flippy-fallback.uimg ${DIR_INSTALL}/mnt/
    cp  ${DIR_INSTALL}/boot/vmlinuz-linux-aarch64-flippy ${DIR_INSTALL}/mnt/
    cp  -r ${DIR_INSTALL}/boot/dtbs ${DIR_INSTALL}/mnt/
    cp  /boot/${UBOOT_OVERLOAD} ${DIR_INSTALL}/mnt/u-boot.emmc
    mv ${DIR_INSTALL}/mnt/dtbs/linux-aarch64-flippy/amlogic ${DIR_INSTALL}/mnt/dtbs/linux-aarch64-flippy/amlogic_bk
    cp -r ${DIR_INSTALL}/mnt/dtb/amlogic ${DIR_INSTALL}/mnt/dtbs/linux-aarch64-flippy/

    echo -e "${INFO} Update the relevant parameters."
    ophub_release_file="${DIR_INSTALL}${ophub_release_file}"
    armbian_release_file="${DIR_INSTALL}${armbian_release_file}"
    sed -i "s|^FDTFILE=.*|FDTFILE='${FDTFILE}'|g" ${ophub_release_file}
    sed -i "s|^UBOOT_OVERLOAD=.*|UBOOT_OVERLOAD='${UBOOT_OVERLOAD}'|g" ${ophub_release_file}
    sed -i "s|^MAINLINE_UBOOT=.*|MAINLINE_UBOOT='/usr/lib/u-boot/${MAINLINE_UBOOT}'|g" ${ophub_release_file}
    sed -i "s|^BOOTLOADER_IMG=.*|BOOTLOADER_IMG='/usr/lib/u-boot/${BOOTLOADER_IMG}'|g" ${ophub_release_file}
    sed -i "s|^SOC=.*|SOC='${AMLOGIC_SOC}'|g" ${ophub_release_file}
    sed -i "s|^K510=.*|K510='${K510}'|g" ${ophub_release_file}
    sed -i "s|^ROOTFS_TYPE=.*|ROOTFS_TYPE='${file_system_type}'|g" ${ophub_release_file}
    sed -i "s|^BOOT_CONF=.*|BOOT_CONF='${BOOT_CONF}'|g" ${ophub_release_file}
    sed -i "s|^DISK_TYPE=.*|DISK_TYPE='emmc'|g" ${ophub_release_file}
    sed -i "s|^MLUBOOT_STATUS=.*|MLUBOOT_STATUS='${auto_mainline_uboot}'|g" ${ophub_release_file}
    sed -i "s|^AMPART_STATUS=.*|AMPART_STATUS='${AMPART_STATUS}'|g" ${ophub_release_file}
    sed -i "s|^BOARD_NAME=.*|BOARD_NAME=\"Aml ${AMLOGIC_SOC}\"|g" ${armbian_release_file}

    # Set interfaces macaddr
    interfaces_file="${DIR_INSTALL}/etc/network/interfaces"
    [[ -f "${interfaces_file}" ]] && sed -i "s|hwaddress ether.*|hwaddress ether ${random_macaddr}:AA|g" ${interfaces_file}

    # Optimize wifi/bluetooth module
    [[ -d "${DIR_INSTALL}/usr/lib/firmware/brcm" ]] && (
        cd ${DIR_INSTALL}/usr/lib/firmware/brcm/ && mv -f ../*.hcd . 2>/dev/null

        # gtking/gtking pro is bcm4356 wifi/bluetooth, wifi5 module AP6356S
        sed -e "s/macaddr=.*/macaddr=${random_macaddr}:00/" "brcmfmac4356-sdio.txt" >"brcmfmac4356-sdio.azw,gtking.txt"
        # gtking/gtking pro is bcm4356 wifi/bluetooth, wifi6 module AP6275S
        sed -e "s/macaddr=.*/macaddr=${random_macaddr}:01/" "brcmfmac4375-sdio.txt" >"brcmfmac4375-sdio.azw,gtking.txt"
        # Phicomm N1 is bcm43455 wifi/bluetooth
        sed -e "s/macaddr=.*/macaddr=${random_macaddr}:02/" "brcmfmac43455-sdio.txt" >"brcmfmac43455-sdio.phicomm,n1.txt"
        # MXQ Pro+ is AP6330(bcm4330) wifi/bluetooth
        sed -e "s/macaddr=.*/macaddr=${random_macaddr}:03/" "brcmfmac4330-sdio.txt" >"brcmfmac4330-sdio.crocon,mxq-pro-plus.txt"
        # HK1 Box & H96 Max X3 is bcm54339 wifi/bluetooth
        sed -e "s/macaddr=.*/macaddr=${random_macaddr}:04/" "brcmfmac4339-sdio.ZP.txt" >"brcmfmac4339-sdio.amlogic,sm1.txt"
        # old ugoos x3 is bcm43455 wifi/bluetooth
        sed -e "s/macaddr=.*/macaddr=${random_macaddr}:05/" "brcmfmac43455-sdio.txt" >"brcmfmac43455-sdio.amlogic,sm1.txt"
        # new ugoos x3 is brm43456
        sed -e "s/macaddr=.*/macaddr=${random_macaddr}:06/" "brcmfmac43456-sdio.txt" >"brcmfmac43456-sdio.amlogic,sm1.txt"
        # x96max plus v5.1 (ip1001m phy) adopts am7256 (brcm4354)
        sed -e "s/macaddr=.*/macaddr=${random_macaddr}:07/" "brcmfmac4354-sdio.txt" >"brcmfmac4354-sdio.amlogic,sm1.txt"
    )

    rm -f ${DIR_INSTALL}/usr/sbin/armbian-tf

    sync && sleep 3
    #umount ${DIR_INSTALL}/mnt
    #umount -f ${DIR_INSTALL}
    [[ "${?}" -eq "0" ]] || error_msg "Failed to umount [ ${DIR_INSTALL} ]."
}

# Check script permission
[[ "$(id -u)" == "0" ]] || error_msg "Please run this script as root: [ sudo $0 ]"
echo -e "${STEPS} Start install Armbian to eMMC..."

# Check dependencies
check_depends
# Initialize all variables
init_var "${@}"
# Display the model list
show_aml_model
# Set the type of file system
set_rootfs_type
# Create emmc partition
create_partition
# Copy bootfs partition files
copy_bootfs
# Copy rootfs partition files
copy_rootfs

echo -e "${SUCCESS} Successful installed, please unplug the USB, re-insert the power supply to start the Armbian."
exit 0
